/**
 * Copyright 2015 ABSir's Studio
 * 
 * All right reserved
 *
 * Create on 2015年6月15日 上午10:06:22
 */
package com.absir.appserv.slave.service;

import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.absir.appserv.slave.bean.JMasterSynch;
import com.absir.appserv.system.adapter.SocketAdapter;
import com.absir.appserv.system.converter.BodyMsgPack.CallbackMessagePack;
import com.absir.appserv.system.dao.BeanDao;
import com.absir.appserv.system.dao.utils.QueryDaoUtils;
import com.absir.appserv.system.helper.HelperDatabind;
import com.absir.appserv.system.service.SlaveService;
import com.absir.async.value.Async;
import com.absir.bean.basis.Base;
import com.absir.bean.core.BeanFactoryUtils;
import com.absir.bean.inject.value.Bean;
import com.absir.context.schedule.value.Schedule;
import com.absir.core.util.UtilAtom;
import com.absir.orm.transaction.value.Transaction;

/**
 * @author absir
 *
 */
@SuppressWarnings("unchecked")
@Base
@Bean
public class SlaverMasterService {

	/** ME */
	public static final SlaverMasterService ME = BeanFactoryUtils.get(SlaverMasterService.class);

	/** LOGGER */
	protected static final Logger LOGGER = LoggerFactory.getLogger(SlaverMasterService.class);

	/**
	 * 添加同步
	 * 
	 * @param id
	 * @param uri
	 * @param postData
	 */
	@Transaction
	public boolean addMasterSynch(String id, String uri, Object postData) {
		JMasterSynch masterSynch = new JMasterSynch();
		masterSynch.setId(id);
		masterSynch.setUri(uri);
		masterSynch.setUpdateTime(System.currentTimeMillis());
		try {
			masterSynch.setPostData(postData == null ? null : postData.getClass() == byte[].class ? (byte[]) postData
					: HelperDatabind.writeAsBytes(postData));
			BeanDao.getSession().merge(masterSynch);
			ME.checkSyncs();
			return true;

		} catch (Exception e) {

			LOGGER.error("addMasterSynch failed " + uri + " => " + postData, e);
		}

		return false;
	}

	/**
	 * 服务区同步完成
	 * 
	 * @param masterSynch
	 * @param updateTime
	 */
	@Transaction
	public void syncComplete(JMasterSynch masterSynch, long updateTime) {
		QueryDaoUtils.createQueryArray(BeanDao.getSession(),
				"UPDATE JMasterSynch o SET o.synched = ? WHERE o.id = ? AND o.updateTime = ?", true, masterSynch.getId(),
				updateTime).executeUpdate();
	}

	/**
	 * 检查数据同步
	 */
	@Async(notifier = true)
	@Transaction(readOnly = true)
	@Schedule(fixedDelay = 300000, initialDelay = 20000)
	public void checkSyncs() {
		Iterator<JMasterSynch> iterator = QueryDaoUtils.createQueryArray(BeanDao.getSession(),
				"SELECT o FROM JMasterSynch o WHERE o.synched = ?", false).iterate();
		final UtilAtom atom = new UtilAtom();
		while (iterator.hasNext()) {
			final JMasterSynch masterSynch = iterator.next();
			try {
				atom.increment();
				final long updateTime = masterSynch.getUpdateTime();
				SlaveService.ME.sendData(masterSynch.getUri(), masterSynch.getPostData(), new CallbackMessagePack<String>() {

					@Override
					public void doWithBean(String bean, boolean ok, byte[] buffer, SocketAdapter adapter) {

						try {
							if (ok) {
								ME.syncComplete(masterSynch, updateTime);
							}

						} finally {
							atom.decrement();
						}
					}

				});

			} catch (Exception e) {

				LOGGER.error("checkSyncs " + masterSynch.getId() + " " + masterSynch.getUri() + " => " + masterSynch.getPostData(),
						e);
				atom.decrement();
			}
		}

		atom.await();
	}
}
